object TraitDemo extends App {
  import scala.collection.mutable

  // 1. 定义基础实体类
  class CampusEntity(val id: String, val name: String) {
    override def toString: String = s"$name($id)"
  }

  // 2. 定义特质：可预约
  trait Bookable {
    // 抽象方法：预约
    def book(userId: String, date: String): Boolean

    // 抽象方法：取消预约
    def cancelBooking(userId: String, date: String): Boolean

    // 具体方法：检查是否可预约
    def isBookable(date: String): Boolean = {
      // 简单实现：周末不可预约
      val dayOfWeek = java.time.LocalDate.parse(date).getDayOfWeek.getValue
      dayOfWeek >= 1 && dayOfWeek <= 5  // 1-5是工作日
    }
  }

  // 3. 定义特质：可评价
  trait Rateable {
    // 存储评价
    private val ratings = mutable.ListBuffer.empty[(String, Double, String)]  // (用户ID, 评分, 评论)

    // 抽象方法：获取实体名称
    def entityName: String

    // 具体方法：添加评价
    def addRating(userId: String, score: Double, comment: String): Unit = {
      if (score >= 1 && score <= 5) {
        ratings += ((userId, score, comment))
        println(s"已添加对${entityName}的评价：$score 分")
      } else {
        println("评分必须在1-5之间")
      }
    }

    // 具体方法：获取平均评分
    def averageRating: Double = {
      if (ratings.isEmpty) 0.0
      else ratings.map(_._2).sum / ratings.size
    }

    // 具体方法：获取所有评价
    def getRatings: List[(String, Double, String)] = ratings.toList
  }

  // 4. 定义特质：可统计使用次数
  trait Usable {
    // 记录使用次数
    private var useCount = 0

    // 具体方法：记录使用
    def recordUsage(): Unit = {
      useCount += 1
    }

    // 具体方法：获取使用次数
    def getUseCount: Int = useCount

    // 抽象方法：获取使用说明
    def usageInstructions: String
  }

  // 5. 定义教室类：混入可预约和可统计特质
  class Classroom(
                   id: String,
                   name: String,
                   val capacity: Int,
                   val location: String
                 ) extends CampusEntity(id, name) with Bookable with Usable {

    // 存储预约信息
    private val bookings = mutable.Map.empty[(String, String), String]  // (用户ID, 日期) -> 用途

    // 实现Bookable特质的方法
    override def book(userId: String, date: String): Boolean = {
      if (isBookable(date) && !bookings.contains((userId, date))) {
        bookings((userId, date)) = "教学"
        println(s"教室${name}已被${userId}预约于${date}使用")
        true
      } else {
        println(s"教室${name}在${date}无法预约")
        false
      }
    }

    override def cancelBooking(userId: String, date: String): Boolean = {
      if (bookings.contains((userId, date))) {
        bookings.remove((userId, date))
        println(s"教室${name}在${date}的预约已取消")
        true
      } else {
        println(s"未找到教室${name}在${date}的预约")
        false
      }
    }

    // 实现Usable特质的方法
    override def usageInstructions: String =
      s"教室${name}可容纳${capacity}人，请保持整洁"
  }

  // 6. 定义课程类：混入可评价特质
  class Course(
                id: String,
                name: String,
                val teacher: String,
                val credit: Double
              ) extends CampusEntity(id, name) with Rateable {

    // 实现Rateable特质的抽象方法
    override def entityName: String = s"课程${name}"
  }

  // 7. 定义实验室类：混入所有特质
  class Laboratory(
                    id: String,
                    name: String,
                    val equipment: List[String]
                  ) extends CampusEntity(id, name) with Bookable with Rateable with Usable {

    // 存储预约信息
    private val bookings = mutable.Map.empty[(String, String), String]

    // 实现Bookable特质的方法
    override def book(userId: String, date: String): Boolean = {
      if (isBookable(date) && !bookings.contains((userId, date))) {
        bookings((userId, date)) = "实验"
        println(s"实验室${name}已被${userId}预约于${date}使用")
        true
      } else {
        false
      }
    }

    override def cancelBooking(userId: String, date: String): Boolean = {
      if (bookings.contains((userId, date))) {
        bookings.remove((userId, date))
        true
      } else {
        false
      }
    }

    // 实现Rateable特质的方法
    override def entityName: String = s"实验室${name}"

    // 实现Usable特质的方法
    override def usageInstructions: String =
      s"实验室${name}包含设备：${equipment.mkString(",")}，使用前请阅读安全指南"
  }

  // 8. 使用混入特质的类
  // 教室示例
  val classroom = new Classroom("CR101", "一号教学楼101", 50, "一号教学楼1层")
  classroom.book("T1001", "2025-09-10")
  classroom.book("T1002", "2025-09-10")  // 同一时间重复预约
  classroom.recordUsage()
  println(s"教室使用次数：${classroom.getUseCount}")
  println(s"教室使用说明：${classroom.usageInstructions}")

  // 课程示例
  val course = new Course("C101", "Scala编程", "李老师", 3.0)
  course.addRating("S2025001", 4.5, "非常实用")
  course.addRating("S2025002", 5.0, "老师讲得很好")
  println(s"课程平均评分：${course.averageRating}")

  // 实验室示例（多特质组合）
  val lab = new Laboratory("LAB01", "计算机实验室", List("服务器", "交换机", "PC机"))
  lab.book("T1001", "2025-09-12")
  lab.addRating("T1001", 4.0, "设备齐全")
  lab.recordUsage()
  println(s"实验室平均评分：${lab.averageRating}")
  println(s"实验室使用次数：${lab.getUseCount}")
}